﻿namespace BEGDC.CC.Web.EZVisit.Common
{
    #region Using Directives

    using System;
    using System.Data;
    using System.Linq;
    using System.Web.UI.WebControls;
    using ASBCC.Business;
    using ASBCC.Database.Entity;
    using ASBCC.Database.Service;
    using ASBCC.Workflow.Client;
    using BL.Common;
    using BL.Common.Query;
    using Utility.Castle;
    using Utility.Extensions;
    using Workflow;

    #endregion

    public partial class EZVRequestContract : BasePage
    {
        #region Properties

        internal const string SessionKey = "EZVRequestContractInfo_";

        private string ApplicationSessionKey
        {
            get
            {
                return this.Request.QueryString["sn"];
            }
        }

        protected int RowID
        {
            get
            {
                return Convert.ToInt32(this.Request["ContractInfoId"]);
            }
        }

        #endregion

        protected void Page_Load(object sender, EventArgs e)
        {
            if (!this.IsPostBack && this.RowID > 0)
            {
                this.InitForm();
            }
        }

        protected void btnSave_Click(object sender, EventArgs e)
        {
            if (!this.Page.IsValid)
            {
                return;
            }

            this.UpdateContractInfoSession();

            if (this.secContract1.Visible)
            {
                this.UpdateContractTableAtFncStep();
            }

            this.Response.Write(@"<script type=""text/javascript"">window.close();window.returnValue='reload';</script>");
        }

        protected void ddlWBSE_SelectedIndexChanged(object sender, EventArgs e)
        {
            string[] v = this.ddlWBSE.SelectedValue.Split('|');

            this.lblWBSED.Text = v[0];
            this.lblWBSP.Text = string.Format("{0}<br/>{1}", v[1], v[2]);
        }

        private void InitForm()
        {
            var dt = this.Session[SessionKey + this.ApplicationSessionKey] as DataTable;
            var app = this.Session[this.ApplicationSessionKey] as EZVisitApplicationTableEntity;

            // Session expired.
            if (dt == null || app == null)
            {
                return;
            }

            DataRow row = dt.Rows[this.RowID - 1];

            this.tbContractNo.Text = row["ContractNo"].ToString();
            this.tbReservedBudget.Text = row["EstimatedTotalCost"].ToString();

            // Set view for FNC Controller
            bool isFnc = false;

            if (app.CurrentStep.IsNotNullOrWhiteSpace() && app.FNCController.IsNotNullOrWhiteSpace())
            {
                isFnc = ValueIncludes(app.CurrentStep, EZVisitActivityNameConsts.FNC_Controller);
                isFnc &= ValueIncludes(app.FNCController, this.UserInfo.NameEN);
                isFnc &= !app.ProcessStatus.Equals(ProcessStatusConsts.Withdrawn);
            }

            if (isFnc)
            {
                this.SetFNCViewVisibility();

                this.SetFNCViewData(row);
            }
        }

        private void UpdateContractInfoSession()
        {
            if (this.RowID < 0)
            {
                return;
            }

            var dt = this.Session[SessionKey + this.ApplicationSessionKey] as DataTable;

            // Session expired.
            if (dt == null)
            {
                return;
            }

            string contractNo = this.tbContractNo.Text.Trim();

            var ezvService = new EZVisitBusiness();

            var ds = ezvService.GetContractInfoByNo(contractNo);

            var contractTable = ds.Tables[0];

            decimal accurAmount = 0, visitAccurAmount = 0, trainingAccurAmount = 0;
            decimal actualExpense = 0, visitActualExpense = 0, trainingActualExpense = 0;

            if (contractTable.Rows.Count != 0)
            {
                var contract = contractTable.Rows[0];

                accurAmount = contract.Field<decimal>("AccurAmount");
                visitAccurAmount = contract.Field<decimal>("VisitAccurAmount");
                trainingAccurAmount = contract.Field<decimal>("TrainingAccurAmount");
                actualExpense = contract.Field<decimal>("ActualExpense");
                visitActualExpense = contract.Field<decimal>("VisitActualExpense");
                trainingActualExpense = contract.Field<decimal>("TrainingActualExpense");
            }

            DataRow row;

            if (this.RowID == 0)
            {
                row = dt.NewRow();
                row["ContractNo"] = contractNo;
                string cost = this.tbReservedBudget.Text.Trim();
                row["EstimatedTotalCost"] = cost;
                row["ApplicantCost"] = cost;
                row["VisitCost"] = cost;
                row["TrainingCost"] = 0;
                row["AccurAmount"] = accurAmount;
                row["VisitAccurAmount"] = visitAccurAmount;
                row["TrainingAccurAmount"] = trainingAccurAmount;
                row["ActualExpense"] = actualExpense;
                row["VisitActualExpense"] = visitActualExpense;
                row["TrainingActualExpense"] = trainingActualExpense;
                row["CreateAt"] = DateTime.Now;
                row["CreateBy"] = this.UserInfo.NameEN;
                row["IsEnabled"] = true;
                dt.Rows.Add(row);
            }
            else if (this.RowID > 0)
            {
                row = dt.Rows[this.RowID - 1];
                row["ContractNo"] = contractNo;

                if (this.tbReservedBudget.Visible)
                {
                    string cost = this.tbReservedBudget.Text.Trim();
                    row["EstimatedTotalCost"] = cost;
                    row["ApplicantCost"] = cost;
                    row["VisitCost"] = cost;
                    row["TrainingCost"] = 0;
                }

                if (!row.IsNull("ContractItemID"))
                {
                    row["UpdateAt"] = DateTime.Now;
                    row["UpdateBy"] = this.UserInfo.NameEN;
                }

                row["IsEnabled"] = true;
            }

            this.Session[SessionKey + this.ApplicationSessionKey] = SetRowID(dt);
        }

        #region Helpers

        private static DataTable SetRowID(DataTable table)
        {
            if (table != null && table.Rows.Count > 0)
            {
                for (int i = 1; i <= table.Rows.Count; i++)
                {
                    table.Rows[i - 1]["RowId"] = i.ToString();
                }
            }
            return table;
        }

        private static bool ValueIncludes(string src, string dest)
        {
            src = ";" + src + ";";
            dest = ";" + dest + ";";
            return src.IndexOf(dest, StringComparison.InvariantCultureIgnoreCase) != -1;
        }

        #endregion

        #region FNC Input

        private void SetFNCViewVisibility()
        {
            this.tbContractNo.Visible = this.tbReservedBudget.Visible = false;

            this.rfv1.Enabled = this.rfv2.Enabled = false;
            this.rev1.Enabled = false;

            this.secContract1.Visible = this.secContract2.Visible = true;
            this.secContract3.Visible = this.secContract4.Visible = true;
            this.secContract0.Visible = this.secContract5.Visible = true;
            this.secContract7.Visible = true;

            this.txtVisitBudget.Focus();
        }

        private void BindLegalEntities()
        {
            var queryService = (IQuery)AppContainer.Instance[ServiceConst.QueryService];
            this.edt_LegalEntity.DataSource = queryService.GetAllLegalEntity();
            this.edt_LegalEntity.DataTextField = "LegalEntityName";
            this.edt_LegalEntity.DataValueField = "LegalEntityID";
            this.edt_LegalEntity.DataBind();
        }

        private void SetFNCViewData(DataRow originalDataRow)
        {
            this.vw_ContractNo.Text = originalDataRow["ContractNo"].ToString();
            this.tbReservedBudget.Text = this.vw_ReservedBudget.Text = originalDataRow["EstimatedTotalCost"].ToString();
            this.vw_TotalBudget.Text = originalDataRow["EstimatedTotalCost"].ToString();

            this.txtVisitBudget.Text = originalDataRow["VisitCost"].ToString();
            this.txtTrainBudget.Text = originalDataRow["TrainingCost"].ToString();
            this.txtCostCenter.Text = originalDataRow["CostCenter"].ToString();

            this.BindLegalEntities();

            if (!originalDataRow.IsNull("LegalEntityID"))
            {
                this.edt_LegalEntity.SelectedValue = originalDataRow["LegalEntityID"].ToString();
            }

            this.GetContractDetails(originalDataRow["ContractNo"].ToString());

            if (this.ddlWBSE.Items.Count > 0)
            {
                if (originalDataRow.IsNull("WBSE"))
                {
                    string[] v = this.ddlWBSE.SelectedValue.Split('|');

                    this.lblWBSED.Text = v[0];
                    this.lblWBSP.Text = string.Format("{0}<br/>{1}", v[1], v[2]);
                }
                else
                {
                    foreach (ListItem li in this.ddlWBSE.Items.Cast<ListItem>().Where(li => li.Text.Equals(originalDataRow["WBSE"].ToString())))
                    {
                        li.Selected = true;
                        break;
                    }

                    this.lblWBSED.Text = originalDataRow["WBSED"].ToString();
                    this.lblWBSP.Text = string.Format("{0}<br />{1}", originalDataRow["WBSP"], originalDataRow["WBSPD"]);
                }
            }

            if (!originalDataRow.IsNull("InvoiceHeader"))
            {
                this.lblInvoiceHeader.Text = originalDataRow["InvoiceHeader"].ToString();
            }
        }

        private static void UpdateContractOngoingAmount(DataRow contractRow, DataTable dtOngoing)
        {
            decimal? visitOnGoingAmount = new decimal?();
            decimal? trainingOnGoingAmount = new decimal?();
            decimal? onGoingAmount = new decimal?();

            if (dtOngoing.Rows.Count != 0)
            {
                var row = dtOngoing.Rows[0];

                visitOnGoingAmount = row.Field<decimal>("VisitCost") - contractRow.Field<decimal>("VisitCost");
                trainingOnGoingAmount = row.Field<decimal>("TrainingCost") - contractRow.Field<decimal>("TrainingCost");
                onGoingAmount = visitOnGoingAmount + trainingOnGoingAmount;
            }

            contractRow["OnGoingAmount"] = onGoingAmount != null ? (object)onGoingAmount : DBNull.Value;

            contractRow["VisitOnGoingAmount"] = visitOnGoingAmount != null ? (object)visitOnGoingAmount : DBNull.Value;

            contractRow["TrainingOnGoingAmount"] = trainingOnGoingAmount != null ? (object)trainingOnGoingAmount : DBNull.Value;
        }

        private void GetContractDetails(string contractNo)
        {
            var ezvService = new EZVisitBusiness();

            var ds = ezvService.GetContractInfoByNo(contractNo);

            var dt = ds.Tables[0];
            string invoiceHeader = "";
            string companyCode = "";
            decimal AccurAmount=0, VisitAccurAmount=0, TrainingAccurAmount=0, ActualExpense=0, VisitActualExpense=0, TrainingActualExpense=0;
            if (dt.Rows.Count > 0)
            {
                this.lblInvoiceHeader.Text = dt.Rows[0]["InvoiceHeader"].ToString();
                invoiceHeader = dt.Rows[0]["InvoiceHeader"].ToString();
                companyCode = dt.Rows[0]["CompanyCode"].ToString();
                AccurAmount = (decimal)dt.Rows[0]["AccurAmount"];
                VisitAccurAmount = (decimal)dt.Rows[0]["VisitAccurAmount"];
                TrainingAccurAmount = (decimal)dt.Rows[0]["TrainingAccurAmount"];
                ActualExpense = (decimal)dt.Rows[0]["ActualExpense"];
                VisitActualExpense = (decimal)dt.Rows[0]["VisitActualExpense"];
                TrainingActualExpense = (decimal)dt.Rows[0]["TrainingActualExpense"];

            }

            foreach (DataRow row in dt.Rows.Cast<DataRow>().Where(row => row.IsNull("WBSE")))
            {
                row.Delete();
            }

            dt.AcceptChanges();

            if (dt.Rows.Count == 0)
            {
                var row = dt.NewRow();
                row["ContractNo"] = contractNo;
                row["AccurAmount"] = AccurAmount;
                row["VisitAccurAmount"] = VisitAccurAmount;
                row["TrainingAccurAmount"] = TrainingAccurAmount;
                row["ActualExpense"] = ActualExpense;
                row["VisitActualExpense"] = VisitActualExpense;
                row["TrainingActualExpense"] = TrainingActualExpense;
                row["WBSE"] = "N/A";
                row["WBSED"] = string.Empty;
                row["WBSP"] = "N/A";
                row["WBSPD"] = string.Empty;
                row["CompanyCode"] = companyCode;
                row["InvoiceHeader"] = invoiceHeader;

                dt.Rows.Add(row);
            }


            var dtWBSE = ds.Tables[2];


            foreach (DataRow row in dtWBSE.Rows.Cast<DataRow>().Where(row => row.IsNull("WBSE")))
            {
                row.Delete();
            }

            dtWBSE.AcceptChanges();

            if (dtWBSE.Rows.Count==0)
            {
                var row = dtWBSE.NewRow();
                row["WBSE"] = "N/A";
                row["WBSED"] = string.Empty;
                row["WBSP"] = "N/A";
                row["WBSPD"] = string.Empty;
                dtWBSE.Rows.Add(row);
            }

            foreach (DataRow row in dtWBSE.Rows)
            {
                if (row.IsNull("WBSE"))
                {
                    row["WBSE"] = "N/A";
                    row["WBSED"] = string.Empty;
                    row["WBSP"] = "N/A";
                    row["WBSPD"] = string.Empty;
                }

                string v = string.Format("{0}|{1}|{2}|{3}", row["WBSED"], row["WBSP"], row["WBSPD"], row["WBSE"]);

                this.ddlWBSE.Items.Add(new ListItem(row["WBSE"].ToString(), v));
            }

            this.SyncSessionWithDataBase(dt.Rows[0], ds.Tables[1]);
        }

        private void SyncSessionWithDataBase(DataRow contractInfo, DataTable dtOngoing)
        {
            var dt = this.Session[SessionKey + this.ApplicationSessionKey] as DataTable;

            // Session expired.
            if (dt == null)
            {
                return;
            }

            DataRow row = dt.Rows[this.RowID - 1];

            row["AccurAmount"] = contractInfo["AccurAmount"];
            row["VisitAccurAmount"] = contractInfo["VisitAccurAmount"];
            row["TrainingAccurAmount"] = contractInfo["TrainingAccurAmount"];
            row["ActualExpense"] = contractInfo["ActualExpense"];
            row["VisitActualExpense"] = contractInfo["VisitActualExpense"];
            row["TrainingActualExpense"] = contractInfo["TrainingActualExpense"];
            row["CompanyCode"] = contractInfo["CompanyCode"];

            // This DataTable contains the existing contracts used in the EZVisitContractItem table.
            // We'll count the Ongoing amount based on this.
            UpdateContractOngoingAmount(row, dtOngoing);

            this.Session[SessionKey + this.ApplicationSessionKey] = SetRowID(dt);
        }

        private void UpdateContractTableAtFncStep()
        {
            var app = this.Session[this.ApplicationSessionKey] as EZVisitApplicationTableEntity;

            if (app == null)
            {
                return;
            }

            var dt = this.Session[SessionKey + this.ApplicationSessionKey] as DataTable;

            if (dt == null || dt.Rows.Count == 0)
            {
                return;
            }

            DataRow row = dt.Rows[this.RowID - 1];

            var contract = EZVisitContractItemManager.SelectByKeys(Convert.ToInt32(row["ContractItemID"]));

            if (contract != null)
            {
                decimal visitCost, trainingCost;

                decimal.TryParse(this.txtVisitBudget.Text, out visitCost);
                decimal.TryParse(this.txtTrainBudget.Text, out trainingCost);

                app.TotalCost -= row.Field<decimal>("EstimatedTotalCost");
                app.TotalCost += visitCost + trainingCost;

                decimal rate = Convert.ToDecimal(app.ExchangeRate);
                app.TotalCostEUR = app.TotalCost.Value / rate;

                EZVisitApplicationManager.Update(app);

                row["EstimatedTotalCost"] = contract.EstimatedTotalCost = visitCost + trainingCost;
                row["VisitCost"] = contract.VisitCost = visitCost;
                row["TrainingCost"] = contract.TrainingCost = trainingCost;
                row["CostCenter"] = contract.CostCenter = this.txtCostCenter.Text;
                row["LegalEntityID"] = contract.LegalEntityID = Convert.ToInt32(this.edt_LegalEntity.SelectedValue);
                row["LegalEntity"] = contract.LegalEntity = this.edt_LegalEntity.SelectedItem.Text;

                contract.AccurAmount = row.Field<decimal>("AccurAmount");
                contract.VisitAccurAmount = row.Field<decimal>("VisitAccurAmount");
                contract.TrainingAccurAmount = row.Field<decimal>("TrainingAccurAmount");
                contract.ActualExpense = row.Field<decimal>("ActualExpense");
                contract.VisitActualExpense = row.Field<decimal>("VisitActualExpense");
                contract.TrainingActualExpense = row.Field<decimal>("TrainingActualExpense");

                contract.CompanyCode = row.Field<string>("CompanyCode");
                row["InvoiceHeader"] = contract.InvoiceHeader = this.lblInvoiceHeader.Text;

                var v = this.ddlWBSE.SelectedValue.Split('|');

                row["WBSE"] = contract.WBSE = this.ddlWBSE.SelectedItem.Text;
                row["WBSED"] = contract.WBSED = this.lblWBSED.Text;
                row["WBSP"] = contract.WBSP = v[1];
                row["WBSPD"] = contract.WBSPD = v[2];
                row["UpdateBy"] = contract.UpdateBy = this.UserInfo.NameEN;
                row["UpdateAt"] = contract.UpdateAt = DateTime.Now;

                EZVisitContractItemManager.Update(contract);

                var dtOnging = new EZVisitBusiness().GetContractInfoByNo(contract.ContractNo).Tables[1];

                UpdateContractOngoingAmount(row, dtOnging);

                contract.OnGoingAmount = row.Field<decimal>("OnGoingAmount");
                contract.TrainingOnGoingAmount = row.Field<decimal>("TrainingOnGoingAmount");
                contract.VisitOnGoingAmount = row.Field<decimal>("VisitOnGoingAmount");

                row["Balance"] = contract.AccurAmount - contract.ActualExpense - contract.OnGoingAmount - contract.EstimatedTotalCost;
                row["TrainingBalance"] = contract.TrainingAccurAmount - contract.TrainingActualExpense - contract.TrainingOnGoingAmount - contract.TrainingCost;
                row["VisitBalance"] = contract.VisitAccurAmount - contract.VisitActualExpense - contract.VisitOnGoingAmount - contract.VisitCost;
                EZVisitContractItemManager.Update(contract);
            }

            this.Session[SessionKey + this.ApplicationSessionKey] = SetRowID(dt);
        }

        #endregion
    }
}